import { createElement } from 'react';
import dynamic from 'dva/dynamic';
import pathToRegexp from 'path-to-regexp';
import { getMenuData } from './menu';

let routerDataCache;

const modelNotExisted = (app, model) =>
  // eslint-disable-next-line
  !app._models.some(({ namespace }) => {
    return namespace === model.substring(model.lastIndexOf('/') + 1);
  });

// wrapper of dynamic
const dynamicWrapper = (app, models, component) => {
  // () => require('module')
  // transformed by babel-plugin-dynamic-import-node-sync
  if (component.toString().indexOf('.then(') < 0) {
    models.forEach(model => {
      if (modelNotExisted(app, model)) {
        // eslint-disable-next-line
        app.model(require(`../models/${model}`).default);
      }
    });
    return props => {
      if (!routerDataCache) {
        routerDataCache = getRouterData(app);
      }
      return createElement(component().default, {
        ...props,
        routerData: routerDataCache,
      });
    };
  }
  // () => import('module')
  return dynamic({
    app,
    models: () =>
      models.filter(model => modelNotExisted(app, model)).map(m => import(`../models/${m}.js`)),
    // add routerData prop
    component: () => {
      if (!routerDataCache) {
        routerDataCache = getRouterData(app);
      }
      return component().then(raw => {
        const Component = raw.default || raw;
        return props =>
          createElement(Component, {
            ...props,
            routerData: routerDataCache,
          });
      });
    },
  });
};

function getFlatMenuData(menus) {
  let keys = {};
  menus.forEach(item => {
    if (item.children) {
      keys[item.path] = { ...item };
      keys = { ...keys, ...getFlatMenuData(item.children) };
    } else {
      keys[item.path] = { ...item };
    }
  });
  return keys;
}

export const getRouterData = app => {
  const routerConfig = {
    '/': {
      component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
    },

    '/tagMgr/tagList': {
      id: 'tag:tagList',
      component: dynamicWrapper(app, ['tagList'], () => import('../routes/tag/tagList')),
      hideInBreadcrumb: true,
    },
    '/tagMgr/tagSetup': {
      id: 'tag:tagSetup',
      component: dynamicWrapper(app, ['tagSetup'], () => import('../routes/tag/tagSetup')),
      hideInBreadcrumb: true,
    },

    '/resourceMgr/patentList': {
      id: 'tag:tagList',
      component: dynamicWrapper(app, ['patentList'], () => import('../routes/resource/patentList')),
      hideInBreadcrumb: true,
    },
    '/resourceMgr/achievementList': {
      id: 'tag:tagSetup',
      component: dynamicWrapper(app, ['achievementList'], () =>
        import('../routes/resource/achievementList')
      ),
      hideInBreadcrumb: true,
    },
    '/resourceMgr/expertList': {
      id: 'tag:tagList',
      component: dynamicWrapper(app, ['expertsList'], () => import('../routes/resource/expertsList')),
      hideInBreadcrumb: true,
    },
    '/resourceMgr/enterpriseList': {
      id: 'tag:tagSetup',
      component: dynamicWrapper(app, ['enterprise'], () =>
        import('../routes/resource/enterpriseList')
      ),
      hideInBreadcrumb: true,
    },

    '/matchMgr/enterpriseMatch': {
      id: 'tag:tagList',
      component: dynamicWrapper(app, ['enterpriseMatch'], () =>
        import('../routes/match/enterpriseMatch')
      ),
      hideInBreadcrumb: true,
    },
    '/matchMgr/requestMatch': {
      id: 'tag:tagList',
      component: dynamicWrapper(app, ['requestMatch'], () =>
        import('../routes/match/requestMatch')
      ),
      hideInBreadcrumb: true,
    },

    // '/declareMgr/declareCheck': {
    //   id: 'project:declare',
    //   component: dynamicWrapper(app, ['declareCheck'], () => import('../routes/declare/declareCheck')),
    //   hideInBreadcrumb: true
    // },
    // '/declareMgr/declareReview': {
    //   id: 'project:review',
    //   component: dynamicWrapper(app, ['declareReview'], () => import('../routes/declare/declareReview')),
    //   hideInBreadcrumb: true
    // },
    // '/declareMgr/declareResult': {
    //   id: 'project:result',
    //   component: dynamicWrapper(app, ['declareResult'], () => import('../routes/declare/declareResult')),
    //   hideInBreadcrumb: true
    // },

    // '/expertMgr/expertList': {
    //   id: 'expert:management',
    //   component: dynamicWrapper(app, ['expertList'], () => import('../routes/expert/expertList')),
    //   hideInBreadcrumb: true
    // },

    // '/announceMgr/announceList': {
    //   id: 'publicity:management',
    //   component: dynamicWrapper(app, ['announceList'], () => import('../routes/announce/announceList')),
    //   hideInBreadcrumb: true
    // },
    '/systemMgr/member': {
      id: 'system:member',
      component: dynamicWrapper(app, ['member'], () => import('../routes/systemMgr/member')),
      hideInBreadcrumb: true,
    },
    '/systemMgr/role': {
      id: 'system:role',
      component: dynamicWrapper(app, ['role'], () => import('../routes/systemMgr/role')),
      hideInBreadcrumb: true,
    },
    '/systemMgr/admin': {
      id: 'system:admin',
      component: dynamicWrapper(app, ['admin'], () => import('../routes/systemMgr/admin')),
      hideInBreadcrumb: true,
    },
    '/user': {
      component: dynamicWrapper(app, [], () => import('../layouts/UserLayout')),
    },
    '/user/login': {
      component: dynamicWrapper(app, ['login'], () => import('../routes/User/Login')),
    },
    '/user/info': {
      component: dynamicWrapper(app, [], () => import('../routes/User/index')),
    },
  };
  // Get name from ./menu.js or just set it in the router data.
  const menuData = getFlatMenuData(getMenuData());
  // const permission = getPermission();
  // menuData = dealPermissionMenu(menuData, permission);

  // Route configuration data
  // eg. {name,authority ...routerConfig }
  const routerData = {};
  // The route matches the menu
  Object.keys(routerConfig).forEach(path => {
    // Regular match item name
    // eg.  router /user/:id === /user/chen
    const pathRegexp = pathToRegexp(path);
    const menuKey = Object.keys(menuData).find(key => pathRegexp.test(`${key}`));
    let menuItem = {};
    // If menuKey is not empty
    if (menuKey) {
      menuItem = menuData[menuKey];
    }
    let router = routerConfig[path];
    // If you need to configure complex parameter routing,
    // https://github.com/ant-design/ant-design-pro-site/blob/master/docs/router-and-nav.md#%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E8%B7%AF%E7%94%B1%E8%8F%9C%E5%8D%95
    // eg . /list/:type/user/info/:id
    router = {
      ...router,
      name: router.name || menuItem.name,
      authority: router.authority || menuItem.authority,
      hideInBreadcrumb: router.hideInBreadcrumb || menuItem.hideInBreadcrumb,
    };
    routerData[path] = router;
  });
  return routerData;
};
